﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SharpPcap;
using PacketDotNet.Utils;
using Bouyei.NetworkSniffer;
using Bouyei.NetworkSniffer.NetworkDecode;

namespace Bouyei.Discoverer
{
    using Class;

    public partial class MainContainer : Form
    {
        ProcessingBuffer processBuffer;
       
        System.Threading.Timer timingRefreshThread = null;
        SearchForm searchfrm = null;
        object lockobj = new object();
        bool isCapture = false;
        bool isMonitor = false;
        FileStorage fstorage = null;
        BaseClass baseClass = null;

        private void InitPacketList()
        {
            dgvPacketList.Columns.Add("序号", "序号");
            dgvPacketList.Columns.Add("类型", "类型");
            dgvPacketList.Columns.Add("长度", "长度");

            dgvPacketList.Columns.Add("源IP", "源IP");
            dgvPacketList.Columns.Add("源端口", "源端口");
            dgvPacketList.Columns.Add("源MAC", "源MAC");

            dgvPacketList.Columns.Add("目的IP", "目的IP");
            dgvPacketList.Columns.Add("目的端口", "目的端口");
            dgvPacketList.Columns.Add("目的MAC", "目的MAC");

            dgvPacketList.Columns[0].Width = 90;
            dgvPacketList.Columns[1].Width = 80;
            dgvPacketList.Columns[2].Width = 70;
            dgvPacketList.Columns[3].Width = 165;
            dgvPacketList.Columns[4].Width = 80;
            dgvPacketList.Columns[5].Width = 120;
            dgvPacketList.Columns[6].Width = 165;
            dgvPacketList.Columns[7].Width = 80;
            dgvPacketList.Columns[8].Width = 120;

            for (int i = 0; i < dgvPacketList.ColumnCount; ++i)
            {
                GlobalVariable.DisplayTable.Columns.Add(dgvPacketList.Columns[i].Name);
            }
        }

        private void CaptureCommPacketHandler(UnitPacket cpacket)
        {
            try
            {
                lock (lockobj)
                {
                    object[] item = new object[]
                    {
                        cpacket.SNo,
                        cpacket.pType,
                        cpacket.rawBuffer.Length,
                        cpacket.SourceAddress,
                        cpacket.SourcePort,
                        cpacket.SourceMacAddress==null?string.Empty:baseClass.ToMacAddressFormat(cpacket.SourceMacAddress.GetAddressBytes()),
                        cpacket.DestinationAddress,
                        cpacket.DestinactionPort,
                        cpacket.DestinationMacAddress==null?string.Empty:baseClass.ToMacAddressFormat(cpacket.DestinationMacAddress.GetAddressBytes())
                    };

                    GlobalVariable.DisplayTable.Rows.Add(item);

                    GlobalVariable.DisplayList.Add(cpacket);

                    if (isMonitor && GlobalVariable.FilterItems.Count>0)
                    {
                        for (int i = 0; i < GlobalVariable.FilterItems.Count; ++i)
                        {
                           string info= baseClass.ScanFilter(cpacket.pBuffer, GlobalVariable.FilterItems[i]);
                           if (!string.IsNullOrEmpty(info))
                           {
                               BeginInvoke(new MethodInvoker(() =>
                               {
                                   if (rtbDynamicInfo.TextLength >= 1048576)
                                   {
                                       rtbDynamicInfo.Clear();
                                   }
                                   rtbDynamicInfo.AppendText(info);
                                   rtbDynamicInfo.AppendText(Environment.NewLine);

                                   if (rtbDynamicInfo.TextLength >= 1048576)
                                   {
                                       rtbDynamicInfo.Clear();
                                   }
                                   rtbDynamicInfo.AppendText(baseClass.ToString(item));
                                   rtbDynamicInfo.AppendText(Environment.NewLine);

                                   ListViewItem lvitem = new ListViewItem(new string[] { 
                                    cpacket.SourceAddress.ToString(),
                                    cpacket.SourcePort.ToString()
                                     });

                                   lvitem.Tag = cpacket.SNo;

                                   lvResultItems.Items.Add(lvitem);
                                   if (lvResultItems.Items.Count >= 512)
                                   {
                                       for (int c = 0; c < 256; ++c)
                                       {
                                           lvResultItems.Items.RemoveAt(0);
                                       }
                                   }
                               }));
                               break;
                           }
                        }
                    }
                }
            }
            catch
            {

            }
        }

        private void CaptrueDataHandler(RawCapture rawCapture)
        {
            ++GlobalVariable.PacketCount;
            if (GlobalVariable.PacketCount == long.MaxValue) GlobalVariable.PacketCount = 0;

            processBuffer.InPacketQueue(new RawPacket() { rawCaptureInfo = rawCapture });
        }

        private UnitPacket FindPacketOfId(long id)
        {
            for (int i = 0; i < GlobalVariable.DisplayList.Count; ++i)
            {
                if (id.Equals(GlobalVariable.DisplayList[i].SNo))
                {
                    return GlobalVariable.DisplayList[i];
                }
            }
            return null;
        }

        private void SwitchCapture()
        {
            if(isCapture)
            {
                toolSnifferSwitch.Text = "停止抓包";
            }
            else
            {
                toolSnifferSwitch.Text = "开始抓包";
            }
        }

        private void SwitchMonitor()
        {
            if(isMonitor)
            {
                toolMonitorSwitch.Text = "关闭扫描";
            }
            else
            {
                toolMonitorSwitch.Text = "开启扫描";
            }
        }

        private void RefreshDisplayCallback(object obj)
        {
            try
            {
                if (GlobalVariable.DisplayList.Count >= 10240)
                {
                    lock (lockobj)
                    {
                        int c = (GlobalVariable.DisplayList.Count >> 1);
                        GlobalVariable.DisplayList.RemoveRange(0, c);

                        for (int i = 0; i < c; ++i)
                        {
                            GlobalVariable.DisplayTable.Rows.RemoveAt(0);
                        }
                    }
                }
                if (GlobalVariable.DisplayTable.Rows.Count == 0 &&
                                        dgvPacketList.RowCount == 0) return;

                BeginInvoke(new MethodInvoker(() =>
                {
                    dgvPacketList.RowCount = GlobalVariable.DisplayTable.Rows.Count;
                    statusbarPacketCount.Text = string.Format("包总数：{0}", GlobalVariable.PacketCount);
                }));
            }
            catch
            { }
        }

        //构造
        public MainContainer()
        {
            InitializeComponent();
            InitPacketList();
            baseClass = new BaseClass();
            timingRefreshThread = new System.Threading.Timer(new System.Threading.TimerCallback(RefreshDisplayCallback), null, -1, -1);

            try
            {
                GlobalVariable.networkCapture = new NetworkCapture();
                GlobalVariable.networkCapture.CaptureDataEventHandler = new CaptureDataEventArgs(CaptrueDataHandler);

                GlobalVariable.CaptureAdapterList = GlobalVariable.networkCapture.GetCaptureDevices();

                processBuffer = new ProcessingBuffer();
                processBuffer.CaptureCommDataEventHandler = new CaptureCommDataEventArgs(CaptureCommPacketHandler);
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            fstorage = new FileStorage(); 
        }

        private void toolSnifferSwitch_Click(object sender, EventArgs e)
        {
            if (GlobalVariable.CaptureAdapterList != null && GlobalVariable.CaptureAdapterList.Count > 0)
            {
                if(isCapture==false)
                {
                    if (GlobalVariable.CurrentCaptureAdapter == null)
                        GlobalVariable.CurrentCaptureAdapter = GlobalVariable.CaptureAdapterList[0];

                    if (GlobalVariable.networkCapture.StartCapture(GlobalVariable.CurrentCaptureAdapter.CaptureDevice,GlobalVariable.CaptureFilter))
                    {
                        isCapture = true;
                        processBuffer.StartProcessing();
                        timingRefreshThread.Change(3000, 3000);
                    }
                }
                else
                {
                    GlobalVariable.networkCapture.StopCaptrue();
                    isCapture = false;
                    processBuffer.StopProcessing();
                    timingRefreshThread.Change(-1, -1);
                }
                SwitchCapture();
            }
        }

        private void toolMonitorSwitch_Click(object sender, EventArgs e)
        {
            if(isMonitor==false)
            {
                isMonitor = true;
            }
            else
            {
                isMonitor = false;
            }
            SwitchMonitor();
        }

        private void toolClear_Click(object sender, EventArgs e)
        {
            lock (lockobj)
            {
                GlobalVariable.DisplayTable.Rows.Clear();
                GlobalVariable.DisplayList.Clear();
                dgvPacketList.Rows.Clear();
            }
        }

        private void toolSearchContent_Click(object sender, EventArgs e)
        {
            if (searchfrm == null || searchfrm.IsDisposed)
            {
                searchfrm = new SearchForm();
            }
            else searchfrm.Activate();

            searchfrm.Show();
        }

        private void dgvPacketList_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
        {
            try
            {
                if (e.RowIndex < 0 || e.RowIndex >= GlobalVariable.DisplayTable.Rows.Count) return;

                e.Value = GlobalVariable.DisplayTable.Rows[e.RowIndex][e.ColumnIndex];
            }
            catch
            { }
        }

        private void MainContainer_FormClosing(object sender, FormClosingEventArgs e)
        {
            if(isCapture)
            {
                if (MessageBox.Show("当前正在捕获数据包，是否关闭?", "提示", MessageBoxButtons.YesNo) != DialogResult.Yes)
                {
                    e.Cancel = true;
                    return;
                }

                GlobalVariable.networkCapture.StopCaptrue();
                processBuffer.StopProcessing();
                timingRefreshThread.Dispose();
            }
        }

        private void dgvPacketList_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            DataGridViewRow cdr = dgvPacketList.CurrentRow;
            if (cdr == null) return;

            long id = Convert.ToInt64(cdr.Cells[0].Value);

            UnitPacket cpacket = FindPacketOfId(id);
            if (cpacket == null) return;
            if (cpacket.pBuffer != null && cpacket.pBuffer.Length > 0)
            {
                switch (cpacket.pType)
                {
                    case DataPacketType.Tcp:
                        {
                            if (cpacket.DestinactionPort == 80 ||
                                cpacket.DestinactionPort == 8080 ||
                                cpacket.SourcePort == 80 ||
                                cpacket.SourcePort == 8080)
                            {
                                Http http = new Http(cpacket.pBuffer);
                                if (http.IsGZipEncode())
                                {
                                    rtbTextContent.Text = http.GZipDecodeToString();
                                }
                                else
                                {
                                    rtbTextContent.Text = Encoding.Default.GetString(cpacket.pBuffer);
                                }
                            }
                            else
                            {
                                rtbTextContent.Text = Encoding.Default.GetString(cpacket.pBuffer);
                            }
                        }
                        break;
                    default:
                        rtbTextContent.Text = Encoding.Default.GetString(cpacket.pBuffer);
                        break;
                }
            }        

            rtbByteContent.Text =baseClass.BytesToHexString(cpacket.rawBuffer.ActualBytes());
        }

        private void menuSetting_Click(object sender, EventArgs e)
        {
            Configuration frmConfig = new Configuration();
            frmConfig.ShowDialog();
        }

        private void contextmenuBytesSaveAs_Click(object sender, EventArgs e)
        {
            DataGridViewRow cdr = dgvPacketList.CurrentRow;
            if (cdr == null) return;

            long id = Convert.ToInt64(cdr.Cells[0].Value);
           
            UnitPacket cpacket = FindPacketOfId(id);
            if (cpacket == null) return;

            byte[] buf = cpacket.rawBuffer.ActualBytes();
           
            if (buf != null && buf.Length > 0)
            {
                string filename = filename = string.Format("{0}-{1}-{2}.txt",
                   cpacket.SourceMacAddress.ToString(),
                    cpacket.SourcePort,
                   cpacket.SNo);

                string content =baseClass.BytesToStringFormat(buf);
                SaveFileDialog save = new SaveFileDialog();
                save.Filter = "*.txt|(*.txt)";
                save.FileName = filename;
                if (save.ShowDialog() == DialogResult.OK)
                {
                   bool rt= fstorage.Write(save.FileName, content);
                   MessageBox.Show(rt ? "保存完成!" : "保存失败");
                }
            }
        }

        private void menuAbout_Click(object sender, EventArgs e)
        {
            MessageBox.Show("网络数据包嗅探,"+Application.ProductVersion);
        }

        private void menuRule_Click(object sender, EventArgs e)
        {
            FilterRules filterRules = new FilterRules();
            filterRules.ShowDialog();
        }

        private void lvResultItems_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                ListView.SelectedListViewItemCollection items = lvResultItems.SelectedItems;
                foreach (ListViewItem item in items)
                {
                    if (item.Tag != null)
                    {
                        for(int i=0;i<dgvPacketList.RowCount;++i)
                        {
                            if(dgvPacketList.Rows[i].Cells[0].Value.Equals(item.Tag))
                            {
                                dgvPacketList.Rows[i].Selected = true;
                                dgvPacketList.FirstDisplayedScrollingRowIndex = i;
                                break;
                            }
                        }
                    }
                }
            }catch
            { }
        }

        private void 下载驱动ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.winpcap.org/install/default.htm");
        }
    }
}
